package com.qiaoba.module.system.service.impl;

import com.qiaoba.api.auth.constant.SecurityConstant;
import com.qiaoba.api.auth.entity.LoginUser;
import com.qiaoba.api.auth.entity.SecurityUser;
import com.qiaoba.api.auth.entity.dto.RoleDTO;
import com.qiaoba.api.auth.service.AuthConfigApiService;
import com.qiaoba.api.auth.service.SysUserDetailsApiService;
import com.qiaoba.api.system.entity.vo.SysUserVO;
import com.qiaoba.common.base.constant.BaseConstant;
import com.qiaoba.module.system.service.SysMenuService;
import com.qiaoba.module.system.service.SysUserRoleService;
import com.qiaoba.module.system.service.SysUserService;
import com.qiaoba.nosql.redis.service.RedisService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 用户权限验证处理
 *
 * @author ailanyin
 * @version 1.0
 * @since 2022-09-22 04:20:28
 */
@Service
@RequiredArgsConstructor
public class SysUserDetailsServiceImpl implements UserDetailsService, SysUserDetailsApiService {

    private final SysUserService sysUserService;
    private final SysMenuService sysMenuService;
    private final SysUserRoleService sysUserRoleService;
    private final RedisService redisService;
    private final AuthConfigApiService authConfigApiService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SecurityUser user = redisService.getObject(SecurityConstant.USER_DETAILS_REDIS_KEY + username, SecurityUser.class);
        return Objects.isNull(user) ? null : new LoginUser(user.getUserId(), user.getDeptId(), user.getUsername(), user.getNickname(), user.getRoles(), user.getRoleKeys(), user.getPermissions());
    }


    private UserDetails createUserDetails(SysUserVO user) {
        Set<String> perms = sysMenuService.selectPermsByUserId(user.getUserId());
        List<RoleDTO> roles = sysUserRoleService.selectRoleDtoByUserId(user.getUserId(), BaseConstant.NORMAL);
        List<String> roleKeys = roles.stream().map(RoleDTO::getRoleKey).collect(Collectors.toList());
        return new LoginUser(user.getUserId(), user.getDeptId(), user.getUsername(), user.getNickname(), roles, roleKeys, perms);
    }

    @Override
    public UserDetails toCache(String username, String deviceSn) {
        SysUserVO user = sysUserService.selectVoByUsername(username, false);
        UserDetails details = createUserDetails(user);
        SecurityUser securityUser = loginUser2SecurityUser((LoginUser) details);
        redisService.set(SecurityConstant.USER_DETAILS_REDIS_KEY + username, securityUser, authConfigApiService.getTokenExpireTime());
        return details;
    }

    private SecurityUser loginUser2SecurityUser(LoginUser loginUser) {
        SecurityUser securityUser = new SecurityUser();
        securityUser.setUserId(loginUser.getUserId());
        securityUser.setDeptId(loginUser.getDeptId());
        securityUser.setUsername(loginUser.getUsername());
        securityUser.setNickname(loginUser.getNickname());
        securityUser.setRoles(loginUser.getRoles());
        securityUser.setRoleKeys(loginUser.getRoleKeys());
        securityUser.setPermissions(loginUser.getPermissions());
        return securityUser;
    }
}
